﻿////////////////////
// 121214   TienBDH        Add Functions ChangeServer, ChangePort.
//////////////////// 

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Diagnostics;
using System.Linq;
using ExtSite.Classes;

namespace ExtSite
{
    public class ClsFunctions
    {     
        public static string GetNoSerial(string table)
        {
            string noserial = string.Empty;
            if (GB_Vars.GB_NoSerial == null)
            {
                 var db = new DataConfigClassesDataContext();
                 GB_Vars.GB_NoSerial = db.NoSerials.ToList();
            }
            NoSerial nos = GB_Vars.GB_NoSerial.SingleOrDefault(n => n.Table_name.ToLower().Trim() == table.ToLower());
            if (nos != null)
                noserial = nos.No_serial;
            return noserial;
        }

        public static Dictionary<string, string> GetSiteParams()
        {
            var db = new DataConfigClassesDataContext();
            Dictionary<string, string> para = new Dictionary<string, string>();
            foreach (Param p in db.Params)
            {
                para.Add(p.Name, p.Value);
            }
            return para;
        }

        public static string getPara(string key)
        {
            string value = string.Empty;
            if (GB_Vars.SiteParams == null)
            {
                GB_Vars.SiteParams = ClsFunctions.GetSiteParams();
            }
            
            string appConfig = System.Configuration.ConfigurationManager.AppSettings.Get(key);
            if (!string.IsNullOrEmpty(appConfig))
            {
                value = appConfig;
            }
            else
            {
                if(GB_Vars.SiteParams.ContainsKey(key))
                {
                    value = GB_Vars.SiteParams[key];
                }
            }
                             
            return value;
        }               

        /// <summary>
        /// Copy value fromObjt to toObject
        /// </summary>
        /// <param name="fromObj"></param>
        /// <param name="toObj"></param>
        public static void CopyObject(object toObj, object fromObj)
        {
            Type fromObjectType = fromObj.GetType();
            Type toObjectType = toObj.GetType();

            foreach (System.Reflection.PropertyInfo fromProperty in
                fromObjectType.GetProperties())
            {
                if (fromProperty.CanRead )
                {
                    string propertyName = fromProperty.Name;
                    Type propertyType = fromProperty.PropertyType;

                    System.Reflection.PropertyInfo toProperty =
                        toObjectType.GetProperty(propertyName);
                    if (toProperty == null)
                        continue;
                    Type toPropertyType = toProperty.PropertyType;

                    if (toProperty != null && toProperty.CanWrite)
                    {
                        if (toProperty.PropertyType.IsArray)
                        {
                            // Copy each object in an array of objects 
                            Array arr = (Array)fromProperty.GetValue(fromObj, null);
                            if (arr != null)
                            {
                                Array arrCopy = Array.CreateInstance(arr.GetType().GetElementType(), arr.Length);
                                for (int arrIdx = 0; arrIdx < arr.Length; arrIdx++)
                                    arrCopy.SetValue(GetCopy(arr.GetValue(arrIdx)), arrIdx);
                                toProperty.SetValue(toObj, arrCopy, null);
                            }
                        }
                        else
                        {
                            object fromValue = fromProperty.GetValue(fromObj, null);
                            toProperty.SetValue(toObj, fromValue, null);
                        }
                    }
                }
            }
        }

        /// <summary> 
        /// Get a copy of a record for comparison use afterwards 
        /// </summary> 
        /// <param name="obj">the record to copy</param> 
        /// <returns>a copy of the record</returns> 
        public static object GetCopy(object copy, object obj)
        {
            Type type = obj.GetType();

            foreach (PropertyInfo pi in type.GetProperties())
            {
                if (pi.PropertyType.IsArray)
                {
                    // Copy each object in an array of objects 
                    Array arr = (Array)pi.GetValue(obj, null);
                    if (arr != null)
                    {
                        Array arrCopy = Array.CreateInstance(arr.GetType().GetElementType(), arr.Length);
                        for (int arrIdx = 0; arrIdx < arr.Length; arrIdx++)
                            arrCopy.SetValue(GetCopy(arr.GetValue(arrIdx)), arrIdx);
                        pi.SetValue(copy, arrCopy, null);
                    }
                }
                else
                {
                    // Copy each field 
                    pi.SetValue(copy, pi.GetValue(obj, null), null);
                }
            }
            return copy;
        }
        public static object PrepareForNew(object obj, string exfields)
        {
            Type type = obj.GetType();

            foreach (PropertyInfo pi in type.GetProperties())
            {
                // Copy each field 
                PropertyInfo piSpecified = type.GetProperty(pi.Name + "Specified", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
                pi.SetValue(obj, pi.GetValue(obj, null), null);
                if (piSpecified != null && pi.CanWrite == true && pi.GetSetMethod(false) != null)
                {
                    if (pi.PropertyType == typeof(DateTime))
                    {

                        if (!exfields.Contains(pi.Name + ";"))
                        {
                            if (pi.PropertyType == typeof(DateTime))
                            {
                                if (!DateTime.MinValue.Equals(pi.GetValue(obj, null)))
                                {
                                    piSpecified.SetValue(obj, true, null);
                                    //pi.SetValue(obj, System.Data.SqlTypes.SqlDateTime.MinValue.Value.AddHours(7), null);
                                }
                            }
                            else
                            {
                                piSpecified.SetValue(obj, true, null);
                            }
                        }
                    }
                }

            }
            return obj;
        }

        public static object PrepareForUpdate(object obj, string exfields)
        {
            Type type = obj.GetType();

            foreach (PropertyInfo pi in type.GetProperties())
            {
                if (pi.PropertyType.IsArray)
                {
                    // Copy each object in an array of objects 
                    Array arr = (Array)pi.GetValue(obj, null);
                    if (arr != null)
                    {

                        for (int arrIdx = 0; arrIdx < arr.Length; arrIdx++)
                        {
                            ((Array)pi.GetValue(obj, null)).SetValue(PrepareForUpdate(arr.GetValue(arrIdx), exfields), arrIdx);
                        }
                        // pi.SetValue(obj, arr, null);
                        PropertyInfo piSpecified = type.GetProperty(pi.Name + "Specified", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
                        if (piSpecified != null)
                        {
                            piSpecified.SetValue(obj, true, null);
                        }
                    }
                }
                else
                {
                    // Copy each field 
                    PropertyInfo piSpecified = type.GetProperty(pi.Name + "Specified", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
                    pi.SetValue(obj, pi.GetValue(obj, null), null);
                    if (piSpecified != null && pi.CanWrite == true && pi.GetSetMethod(false) != null)
                    {
                        if (pi.PropertyType == typeof(decimal)
                            || pi.PropertyType == typeof(DateTime)
                            || pi.PropertyType == typeof(float)
                            || pi.PropertyType == typeof(int)
                            || pi.PropertyType == typeof(Int16)
                            || pi.PropertyType == typeof(Int32)
                            || pi.PropertyType == typeof(Int64)
                            )
                        {

                            if (!exfields.Contains(";" + pi.Name + ";"))
                            {
                                if (pi.PropertyType == typeof(DateTime))
                                {
                                    if (!DateTime.MinValue.Equals(pi.GetValue(obj, null)))
                                    {
                                        piSpecified.SetValue(obj, true, null);
                                        //pi.SetValue(obj, System.Data.SqlTypes.SqlDateTime.MinValue.Value.AddHours(7), null);
                                    }
                                }
                                else
                                {
                                    piSpecified.SetValue(obj, true, null);
                                }
                            }
                        }
                    }
                    else if (pi.PropertyType == typeof(string))
                    {
                        if (exfields.Contains(";" + pi.Name + ";"))
                        {
                            pi.SetValue(obj, null, null);
                        }
                    }
                }
            }
            return obj;
        }
        public static object GetCopy(object obj)
        {
            Type type = obj.GetType();
            object copy = Activator.CreateInstance(type);
            foreach (PropertyInfo pi in type.GetProperties())
            {
                if (pi.PropertyType.IsArray)
                {
                    // Copy each object in an array of objects 
                    Array arr = (Array)pi.GetValue(obj, null);
                    if (arr != null)
                    {
                        Array arrCopy = Array.CreateInstance(arr.GetType().GetElementType(), arr.Length);
                        for (int arrIdx = 0; arrIdx < arr.Length; arrIdx++)
                        {
                            arrCopy.SetValue(GetCopy(arr.GetValue(arrIdx)), arrIdx);
                        }
                        pi.SetValue(copy, arrCopy, null);
                    }
                }
                else
                {
                    // Copy each field 
                    PropertyInfo piSpecified = type.GetProperty(pi.Name + "Specified", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
                    pi.SetValue(copy, pi.GetValue(obj, null), null);
                    if (piSpecified != null)
                    {
                        piSpecified.SetValue(copy, true, null);
                    }
                }
            }
            return copy;
        }

        /// <summary> 
        /// Prepare record for update 
        /// Set <field> to null if a string field hasn't been updated 
        /// Set <field>Specified to false if a non-string field hasn't been updated 
        /// </summary> 
        /// <param name="obj">record to prepare for update</param> 
        /// <param name="copy">copy of the record (a result of GetCopy)</param> 
        public static void PrepareForUpdate(object obj, object copy)
        {
            Debug.Assert(obj.GetType() == copy.GetType());
            Type type = obj.GetType();
            PropertyInfo[] properties = type.GetProperties();
            for (int idx = 0; idx < properties.Length; idx++)
            {
                PropertyInfo pi = properties[idx];
                if (pi.Name != "Key" &&
                   pi.GetCustomAttributes(typeof(System.Xml.Serialization.XmlIgnoreAttribute), false).Length == 0)
                {
                    if (pi.PropertyType.IsArray)
                    {
                        // Compare an array of objects - recursively 
                        Array objArr = (Array)pi.GetValue(obj, null);
                        Array copyArr = (Array)pi.GetValue(copy, null);
                        for (int objArrIdx = 0; objArrIdx < objArr.Length; objArrIdx++)
                        {
                            object arrObj = objArr.GetValue(objArrIdx);
                            PropertyInfo keyPi = arrObj.GetType().GetProperty("Key");
                            string objKey = (string)keyPi.GetValue(arrObj, null);
                            for (int copyArrIdx = 0; copyArrIdx < copyArr.Length; copyArrIdx++)
                            {
                                object arrCopy = copyArr.GetValue(copyArrIdx);
                                if (objKey == (string)keyPi.GetValue(arrCopy, null))
                                    PrepareForUpdate(arrObj, arrCopy);
                            }
                        }
                    }
                    else
                    {
                        object objValue = pi.GetValue(obj, null);
                        if (objValue != null && objValue.Equals(pi.GetValue(copy, null)))
                        {
                            // Values are the same – signal no change 
                            if (pi.PropertyType == typeof(string))
                            {
                                // Strings doesn’t have a <field>Specified property – set the field to null 
                                pi.SetValue(obj, null, null);
                            }

                            else
                            {
                                // The <field>Specified is autogenerated by Visual Studio as the next property 
                                idx++;
                                PropertyInfo specifiedPi = properties[idx];
                                // Exception if this assumption for some reason isn’t true
                                Debug.Assert(specifiedPi.Name == pi.Name + "Specified");
                                specifiedPi.SetValue(obj, false, null);
                            }
                        }
                    }
                }
            }
        }

        public static object PrepareFieldForUpdate(object obj, string fieldname)
        {
            Type type = obj.GetType();
            PropertyInfo piSpecified = type.GetProperty(fieldname + "Specified", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
            PropertyInfo pi = type.GetProperty(fieldname, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
            pi.SetValue(obj, pi.GetValue(obj, null), null);
            if (piSpecified != null && pi.CanWrite == true && pi.GetSetMethod(false) != null)
            {
                piSpecified.SetValue(obj, true, null);
            }
            return obj;
        }
        // Get file version
        public static string getFileVersion(string filename)
        {
            if (filename.Length == 0) return null;
            string ver = "";
            Assembly asm = null;
            //for (int i = 0; i < filename.Length; i++)
            {
                try
                {
                    asm = Assembly.LoadFrom(string.Format(string.Format("{0}",filename)));
                    if (asm != null) ver = asm.GetName().Version.ToString();
                    else ver = "";
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
           
            return ver;
        }

        // Get file version //dailt 
        public static string getFileVersionByDate()
        {
            System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
            System.IO.FileInfo fileInfo = new System.IO.FileInfo(assembly.Location);
            DateTime lastModified = fileInfo.LastWriteTime;
            return string.Format("{0} - {1}", lastModified.ToShortDateString(), lastModified.ToLongTimeString());
        }

        public static string getObjectProperty(Type type)
        {
            string jsonObj = string.Empty;
            foreach (PropertyInfo pi in type.GetProperties())
            {
                jsonObj = jsonObj + string.Format("{{'FIELD':'{0}','VALUE':'{1}'}},", pi.Name.Replace('_', ' '), pi.Name);
            }
            jsonObj = "[" + jsonObj.Trim().Trim(',') + "]";
            return jsonObj;
        }

        /// <summary>
        /// Check if input value is Date or not.
        /// </summary>
        /// <param name="sdate">Date input.</param>
        /// <returns>True if returns </returns>
        public static bool IsDate(string sdate)
        {
            DateTime dt;
            bool isDate = true;

            try
            {
                dt = DateTime.Parse(sdate);
            }
            catch
            {
                isDate = false;
            }

            return isDate;
        }

        /// <summary>
        /// Get Port of Url.
        /// </summary>
        /// <param name="url">URL string.</param>
        /// <returns>Port.</returns>
        public static int GetPort(string url)
        {
            Uri ur = new Uri(url);
            return ur.Port;
        }

        /// <summary>
        /// 121214.
        /// Change server name of Url.
        /// </summary>
        /// <param name="url">Current Url with existing company name.</param>
        /// <param name="serverName">New Company name to replace.</param>
        /// <returns>New Url with new company name.</returns>
        public static string ChangeServer(string url, string serverName)
        {
            if (!string.IsNullOrEmpty(serverName))
            {
                string os = string.Empty;               
                string newurl = string.Empty;
                string[] urlPaths = url.Split('/');
                os = urlPaths[2];

                string curPort = os.Split(':')[1];

                urlPaths[2] = string.Format("{0}:{1}", serverName, curPort);

                foreach (string s in urlPaths)
                {
                    newurl += s + '/';
                }
                newurl = newurl.Trim('/');
                return newurl;

            }
            return url;
        }

        /// <summary>
        /// 121214
        /// Change server name of Url.
        /// </summary>
        /// <param name="url">Current Url with existing port.</param>
        /// <param name="port">New port to replace.</param>
        /// <returns>New Url with new port.</returns>
        public static string ChangePort(string url, string port)
        {
            Uri link = new Uri(url);
            string oldPort = string.Format("{0}", link.Port.ToString());
            return url.Replace(string.Format(":{0}", oldPort), string.Format(":{0}", port));
        }

        public static string ChageCompany(string url, string company)
        {
            if (url.ToLower().Contains("systemservice"))
                return url;
            if (!string.IsNullOrEmpty(company))
            {
                string newurl = "";
                string[] urlPaths = url.Split('/');
                urlPaths[5] = company.Trim();
                foreach (string s in urlPaths)
                {
                    newurl += s + '/';
                }
                newurl = newurl.Trim('/');
                return newurl;
            }
            return url;
        }

        public static void ChageCompany(ref object obj, string company)
        {
            if (!string.IsNullOrEmpty(company))
            {
                string url = obj.GetType().GetProperty("Url").GetValue(obj, null).ToString();
                string newurl = "";
                string[] urlPaths = url.Split('/');
                urlPaths[5] = company.Trim();
                foreach (string s in urlPaths)
                {
                    newurl += s + '/';
                }
                newurl = newurl.Trim('/');
                obj.GetType().GetProperty("Url").SetValue(obj, newurl, null);
            }
        }

        public static bool IsUserOnline(int userID)
        {
            using (DataConfigClassesDataContext db = new DataConfigClassesDataContext())
            {
                Session session = db.Sessions.Where(x => x.UserID.Value == userID)
                                             .FirstOrDefault();

                return session != null;   
            }
        }
    }
}
